/**
 * @class ElggMap
 */
ElggMap.provide( '', {
	/**
	 * instancia de OpenLayers.Map
	 */
	map: null,
	/**
	 * controlers de OpenLayers predeterminados para el map
	 * @private
	 */
	_mapControls: EM_DEFAULT_MAP_CONTROLS,
	/**
	 * Centro inicial del mapa
	 * @private
	 */
	_initialCenter: new OpenLayers.LonLat(-58.67090, -32.71387),
	/**
	 * Extent inicial para el mapa
	 * @private
	 */
	_initialExtent: null,
	/**
	 * @private
	 */
	_activeLayer: null,
	/**
	 * las features que están marcadas como 'dirty' para ser salvadas por
	 * ELggMap.save()
	 * @type Array. 
	 */
	deleteQueue: [],
	/**
	 * Las emLayer que hayan sido cargadas sobre el mapa
	 * @type Array.
	 */
	layers: [],	
	/*
	 * Opciones predeterminadas para el OpenLayers.Map (ElggMap.map)
	 * Pueden ser seteadas al llamar a buildBaseMap() 
	 * @private
	 */
	_mapSettings: {
		div: 'mapcontainer',
		controls: [],
		//restrictedExtent: new OpenLayers.Bounds(-76, -66, -40.636, -15), 
		tileSize: new OpenLayers.Size(256, 256), 
		/**
		 * displayProjection es utilizada por ArgParser, MousePosition, Permalink Controls...
		 */
		displayProjection: new OpenLayers.Projection('EPSG:4326'), 
		
		units: "degrees", 
		
		// escalas (o niveles de zoom) permitidas en el  mapa
		resolutions: [
			0.06288206988836649,
			0.025152827955346596,
			0.012576413977673298,
			0.0025152827955346596,
			0.0012576413977673298,
			6.288206988836649E-4,
			2.5152827955346593E-4,
			1.2576413977673296E-4,
			6.288206988836648E-5
		]//2.5152827955346596E-5]
		//scales: [25000000, 10000000, 5000000, 1000000, 500000, 250000, 100000, 50000, 25000, 10000]
	},

/**
	 * Construye el mapa base.
	 * - Busca el div con el id predeterminada en el DOM y lo ajusta al tamaño
	 * - Instancia ElggMap.map con las opciones predeterminadas de ElggMap._mapSettings.
	 * - Agrega la capa base al mapa.
	 * - Adds the base layer to the map.
	 * - Setea el extent inicial al que llegue desde el backend.
	 *
	 * @todo Chequear que el id del div sea el de un div existente.
	 * @todo Chequear que ElggMap.map no exista o destruirlo antes de continuar.
	 */
	buildBaseMap: function (buildOptions)
	{
		assertTypeOf(ElggMap._mapSettings.div, 'string');

		if (ElggMap._mapSettings.div === undefined || ElggMap._mapSettings.div === null || ElggMap._mapSettings.div === '')
			ElggMap.log('_mapSettings.div needs to be set with DOM ID for map to render');
		
		if (ElggMap.map instanceof OpenLayers.Map) {
			ElggMap.log('Map already instantiated');
		}
		
		$.extend(true, ElggMap, buildOptions);
		
	
		ElggMap.map = new OpenLayers.Map(ElggMap._mapSettings);
		
		// Controles predeterminados
		ElggMap.map.addControls(ElggMap._mapControls);
		
		// Para mantener actualizado ElggMap.layers
		ElggMap.map.events.register('click',ElggMap, function() {
			ElggMap.Event.fire('basemap.click');
		});
		ElggMap.map.events.register('moveend',ElggMap, function() {
			ElggMap.Event.fire('basemap.moveend');
		});
		ElggMap.map.events.register('movestart',ElggMap, function() {
			ElggMap.Event.fire('basemap.movestart');
		});
		ElggMap.map.events.register('addlayer',ElggMap, ElggMap._onLayerAdded);
		ElggMap.map.events.register('removelayer',ElggMap, ElggMap._onLayerRemoved);
		
		var baseLayer = EM_LAYER_IGNTILES_4326;
		// capa base
		ElggMap.map.addLayer( baseLayer );
		
		// Si  _initialiExtent está seteado, se trata de tener OL.Bounds desde array
		// failsafe to initialCenter
		if ( ElggMap._initialExtent !== null ) {
			var extent = new OpenLayers.Bounds.fromArray( ElggMap._initialExtent );
			if ( extent.CLASS_NAME !== undefined && extent.CLASS_NAME == 'OpenLayers.Bounds' ) {
				ElggMap._initialExtent = extent;
				ElggMap.map.zoomToExtent(ElggMap._initialExtent, true);
			} else {
				ElggMap._initialExtent = null;
				ElggMap.map.setCenter( ElggMap._initialCenter );
			}
		} else {
			ElggMap.map.setCenter(ElggMap._initialCenter);
		}

		if (ElggMap.mapGUID) {
			ElggMap.loadEmMap(ElggMap.mapGUID);
		} else {
			ElggMap.showVisibleMaps();
		}
		ElggMap.Event.fire( "map.built");
	},
	/**
	 * Carga desde la api un objeto y lo vuelva sobre la interfaz
	 * (es decir sobre mapa y paneles)
	 * @param mapGUID GUID del mapa en el backend
	 * @param callback La callback. Recibe lo que devuelve la api
	 */
	loadEmMap: function( mapGUID, callback ) 
	{
		var response;
		
		ElggMap.api('map.getInfo', {guid:mapGUID}, function(response) {
			var map = response.map;
			if ( ! map ) {
				return;
			}
			
			if ( map.layers ) {
				ElggMap.importLayers( map.layers );
			} else {
				ElggMap.log('El mapa no tiene capas')
				return;
			}
			ElggMap.Event.fire( "map.loaded", map );			
		} );
		
		ElggMap.Event.subscribe( "map.loaded", function(map) {

			ElggMap.showMapMetadata(map);
			if ( $.isFunction ( callback ) ) {		
				callback(map);		
		}
		});


		

	},
	/**
	 */
	unloadCurrentMap: function()
	{
		if (ElggMap.editing()) {
			ElggMap.stopEdit();			
		}		
		ElggMap.mapGUID = null;
		$.each(ElggMap.layers, function(i,layer) {
			ElggMap.map.removeLayer(layer);
			layer.destroy();
		})
		ElggMap.showDefaultDetails();
		ElggMap.showVisibleMaps();
		
	},


	/**
	 * Adds the maps layers as KML layers over the map and sets
	 * the listeners for 'featuremodified' and 'loadend' events on the layers.
	 * - On 'loadend' it sets feature attribute saveThis to false and attribute lonlat
	 * to the feature centroid. Also it activates the select tool.
	 *
	 * @param {JSON Object} layersArray the json object passed from the backend that contains
	 * the GUID from the layers of this map
	 */
	importLayers: function(layersArray)
	{
		var l;
		//en estos features voy a recibir un container_guid
		//tal vez podria iterar por esa prop para hacer nuevos layers?
		//por el momento es solo una, la saco de ahi y la seteo como layer.id
		//despues en el form tengo que agregar el campo layer.id o algo asi
		assertTypeOf(layersArray, 'object');
		$.each(layersArray,function(key,value){
			l = new OpenLayers.Layer.emKML(value.title, key);
			
			l.description = value.description;
			l.title = value.title;
			l.guid = key;
			
			ElggMap.map.addLayer(l);
			ElggMap.setActiveLayer(l);
		});
		
	},
	/**
	 */
	setActiveLayer: function(layer)
	{
		ElggMap._activeLayer = layer;
	},	
	
	/**
	 * Handler for the 'removelayer' on the map. Removes
	 * from ElggMap.layers the the layer passed on e.layer
	 * @private
	 * @param {EventObject} e the event object
	 * @todo simplify it
	 */
	_onLayerRemoved: function(e)
	{
		assertInstanceOf(OpenLayers.Layer, e.layer);
		var layerIndex = null;
		for(var i = 0; i < ElggMap.layers.length; i++)
		{
			if (ElggMap.layers[i].id == e.layer.id) layerIndex = i;
		}
		ElggMap.layers.splice(layerIndex,1);
	},
	
	/**
	 * Handler for the 'addlayer' event on the map. If the
	 * recently added layer is not a base layer, saves a reference
	 * to it in ElggMap.layers.
	 * @private
	 * @param {EventObject} e the event object
	 */
	_onLayerAdded: function(e)
	{
		assertInstanceOf(OpenLayers.Layer, e.layer);
		if (e.layer.isBaseLayer !== true)
			ElggMap.layers.push(e.layer);
	},
	
	/**
	 * Triggers the 'moveend' event on the map by recentering
	 * it to the current center.
	 * This function was thought for forcing the populateForm
	 * 
	 * @todo remove this functions when onPan and onZoom are unified
	 */
	_triggerPan: function()
	{
		if(ElggMap.map !== null) ElggMap.map.setCenter(ElggMap.map.center);
	}
});


ElggMap.provide( "", {
	/*
	 * Busca objetos en el servidor
	 * @param object|string q La query a enviar.
	 * @param callback La funciÃ³n a llamar con el resultado
	 */
	search: function(term, callback)
	{
//		if ( ! $.isFunction(callback) ) {
//			callback = function(response) {
//				ElggMap.log(response);
//			}
//		}
		ElggMap.api(
			'feature.search',
			{ q: term },
			callback
		);
	},
	
	_miniCallback: function(response)
	{
		console.log(response);
		if ( $.isArray( response.features ) ) {
			var a = new OpenLayers.Feature.Vector(
				new OpenLayers.Geometry.fromWKT(response.features[0].wkt)
			);
			ElggMap.layers[0].addFeatures(a);
		}
	}
});